/// Upload Repository Interface Contract
/// 
/// This is a specification contract file that defines the complete interface
/// for upload data access operations. Implementation will be provided by
/// pipeline_repository package.
/// 
/// Date: 2025-10-22
/// Feature: 003-upload-repository-api

import '../data-model.md' as doc;

// Pseudo-code representation of the interface contract
// Actual implementation will be in Dart with proper syntax

```dart
/// 上传数据访问接口
/// 
/// 提供上传任务和进度的数据操作抽象接口，不包含具体实现。
/// 实现层（pipeline_repository）负责提供具体的存储实现。
/// 
/// 设计原则：
/// - 所有方法异步（Future/Stream）
/// - 使用领域模型（UploadTask、UploadProgress）
/// - 不暴露存储细节
/// - 不包含业务逻辑
abstract class UploadRepository {
  
  // ==================== CRUD Operations ====================
  
  /// 创建单个上传任务
  /// 
  /// [task] 要创建的任务对象（id 由系统生成，传入的 id 会被忽略）
  /// 
  /// Returns: 包含系统生成 ID 和时间戳的完整任务对象
  /// 
  /// Throws:
  /// - [DataValidationException] 如果任务数据无效（如 userId 为空）
  /// - [RepositoryException] 其他数据库错误
  /// 
  /// Example:
  /// ```dart
  /// final task = UploadTask(
  ///   id: 0,  // 会被忽略
  ///   userId: 'user123',
  ///   status: UploadTaskStatus.pending,
  ///   // ...
  /// );
  /// final created = await repository.createTask(task);
  /// print('Created with ID: ${created.id}');
  /// ```
  Future<UploadTask> createTask(UploadTask task);
  
  /// 批量创建上传任务
  /// 
  /// [tasks] 要创建的任务列表
  /// 
  /// Returns: 包含系统生成 ID 的任务列表
  /// 
  /// Throws:
  /// - [DataValidationException] 如果任何任务数据无效
  /// - [RepositoryException] 其他数据库错误
  /// 
  /// Note: 
  /// - 实现应该使用事务保证原子性（全部成功或全部失败）
  /// - 如果部分失败，整个操作回滚
  Future<List<UploadTask>> createTasks(List<UploadTask> tasks);
  
  /// 通过任务 ID 查询单个任务
  /// 
  /// [id] 任务唯一标识
  /// 
  /// Returns: 
  /// - 任务对象（如果存在）
  /// - null（如果不存在）
  /// 
  /// Example:
  /// ```dart
  /// final task = await repository.getTaskById(123);
  /// if (task != null) {
  ///   print('Found: ${task.status}');
  /// } else {
  ///   print('Task not found');
  /// }
  /// ```
  Future<UploadTask?> getTaskById(int id);
  
  /// 查询所有任务
  /// 
  /// Returns: 所有任务列表（可能为空列表）
  /// 
  /// Warning: 如果任务数量很大，此方法可能性能较差。
  /// 建议使用条件查询或分页查询。
  Future<List<UploadTask>> getAllTasks();
  
  /// 更新任务信息
  /// 
  /// [task] 要更新的任务对象（必须包含有效的 id）
  /// 
  /// Throws:
  /// - [DataNotFoundException] 如果任务不存在
  /// - [DataValidationException] 如果数据无效
  /// - [RepositoryException] 其他数据库错误
  /// 
  /// Note: 
  /// - updatedAt 字段会自动更新为当前时间
  /// - 实现应该更新所有字段（完整替换）
  Future<void> updateTask(UploadTask task);
  
  /// 删除指定任务
  /// 
  /// [id] 要删除的任务 ID
  /// 
  /// Throws:
  /// - [DataNotFoundException] 如果任务不存在
  /// - [RepositoryException] 其他数据库错误
  /// 
  /// Note: 实现应该考虑级联删除相关的 UploadProgress
  Future<void> deleteTask(int id);
  
  /// 批量删除任务
  /// 
  /// [ids] 要删除的任务 ID 列表
  /// 
  /// Throws:
  /// - [RepositoryException] 数据库错误
  /// 
  /// Note: 
  /// - 如果某些 ID 不存在，忽略它们，不抛出异常
  /// - 实现应该使用事务保证原子性
  Future<void> deleteTasks(List<int> ids);
  
  // ==================== Query Operations ====================
  
  /// 按用户 ID 查询任务列表
  /// 
  /// [userId] 用户唯一标识
  /// 
  /// Returns: 该用户的所有任务（可能为空列表）
  /// 
  /// Example:
  /// ```dart
  /// final userTasks = await repository.getTasksByUserId('user123');
  /// print('User has ${userTasks.length} tasks');
  /// ```
  Future<List<UploadTask>> getTasksByUserId(String userId);
  
  /// 按任务状态查询任务列表
  /// 
  /// [status] 任务状态
  /// 
  /// Returns: 指定状态的所有任务
  /// 
  /// Example:
  /// ```dart
  /// final pending = await repository.getTasksByStatus(
  ///   UploadTaskStatus.pending
  /// );
  /// ```
  Future<List<UploadTask>> getTasksByStatus(UploadTaskStatus status);
  
  /// 按组别查询任务列表
  /// 
  /// [groupId] 分组 ID
  /// 
  /// Returns: 该组的所有任务
  /// 
  /// Example:
  /// ```dart
  /// final albumTasks = await repository.getTasksByGroupId('album_123');
  /// ```
  Future<List<UploadTask>> getTasksByGroupId(String groupId);
  
  /// 按用户 ID 和状态查询任务列表
  /// 
  /// [userId] 用户唯一标识
  /// [status] 任务状态
  /// 
  /// Returns: 同时满足两个条件的任务列表
  /// 
  /// Example:
  /// ```dart
  /// final userPending = await repository.getTasksByUserIdAndStatus(
  ///   'user123',
  ///   UploadTaskStatus.pending,
  /// );
  /// ```
  Future<List<UploadTask>> getTasksByUserIdAndStatus(
    String userId,
    UploadTaskStatus status,
  );
  
  // ==================== State Management ====================
  
  /// 更新任务状态
  /// 
  /// [id] 任务 ID
  /// [status] 新状态
  /// 
  /// Throws:
  /// - [DataNotFoundException] 如果任务不存在
  /// 
  /// Note: 
  /// - updatedAt 会自动更新
  /// - 不验证状态转换合法性（由业务层负责）
  Future<void> updateTaskStatus(int id, UploadTaskStatus status);
  
  /// 批量更新任务状态
  /// 
  /// [ids] 任务 ID 列表
  /// [status] 新状态
  /// 
  /// Note: 
  /// - 如果某些 ID 不存在，忽略它们
  /// - 实现应该使用事务
  Future<void> updateTasksStatus(List<int> ids, UploadTaskStatus status);
  
  /// 重置指定状态的任务到新状态
  /// 
  /// 常用于应用启动时重置"上传中"的任务为"待上传"
  /// 
  /// [fromStatus] 源状态
  /// [toStatus] 目标状态
  /// 
  /// Returns: 受影响的任务数量
  /// 
  /// Example:
  /// ```dart
  /// // 应用启动时，重置所有"上传中"的任务
  /// final count = await repository.resetTasksStatus(
  ///   UploadTaskStatus.uploading,
  ///   UploadTaskStatus.pending,
  /// );
  /// print('Reset $count tasks');
  /// ```
  Future<int> resetTasksStatus(
    UploadTaskStatus fromStatus,
    UploadTaskStatus toStatus,
  );
  
  /// 获取下一个待上传任务
  /// 
  /// 按优先级降序、创建时间升序排序，返回第一个待上传任务
  /// 
  /// Returns:
  /// - 优先级最高的待上传任务
  /// - null（如果没有待上传任务）
  /// 
  /// Example:
  /// ```dart
  /// final next = await repository.getNextPendingTask();
  /// if (next != null) {
  ///   print('Next to upload: ${next.id}');
  /// }
  /// ```
  Future<UploadTask?> getNextPendingTask();
  
  /// 获取所有上传中的任务
  /// 
  /// Returns: 状态为 uploading 的任务列表
  Future<List<UploadTask>> getUploadingTasks();
  
  // ==================== Progress Management ====================
  
  /// 创建或更新上传进度
  /// 
  /// [progress] 进度对象
  /// 
  /// Note:
  /// - 如果 taskId 对应的进度不存在，创建新记录
  /// - 如果已存在，更新记录（完整替换）
  /// - 高频调用，实现应该优化性能
  /// 
  /// Example:
  /// ```dart
  /// final progress = UploadProgress(
  ///   taskId: 123,
  ///   progressPercent: 45,
  ///   uploadedBytes: 4500000,
  ///   totalBytes: 10000000,
  ///   // ...
  /// );
  /// await repository.updateProgress(progress);
  /// ```
  Future<void> updateProgress(UploadProgress progress);
  
  /// 查询指定任务的进度
  /// 
  /// [taskId] 任务 ID
  /// 
  /// Returns:
  /// - 进度对象（如果存在）
  /// - null（如果不存在）
  Future<UploadProgress?> getProgressByTaskId(int taskId);
  
  /// 删除进度记录
  /// 
  /// [taskId] 任务 ID
  /// 
  /// Note: 如果不存在，不抛出异常
  Future<void> deleteProgress(int taskId);
  
  /// 查询所有进度记录
  /// 
  /// Returns: 所有进度列表
  Future<List<UploadProgress>> getAllProgress();
  
  // ==================== Stream Operations ====================
  
  /// 监听所有任务变化
  /// 
  /// Returns: 任务列表流，任何任务的创建、更新、删除都会触发新事件
  /// 
  /// Note:
  /// - 订阅时立即发送当前所有任务
  /// - 每次变化发送完整的任务列表
  /// - 记得取消订阅避免内存泄漏
  /// 
  /// Example:
  /// ```dart
  /// final subscription = repository.watchAllTasks().listen((tasks) {
  ///   print('Total tasks: ${tasks.length}');
  /// });
  /// // 使用完后取消订阅
  /// await subscription.cancel();
  /// ```
  Stream<List<UploadTask>> watchAllTasks();
  
  /// 监听单个任务变化
  /// 
  /// [id] 任务 ID
  /// 
  /// Returns: 任务流，该任务更新或删除时触发
  /// 
  /// Note:
  /// - 如果任务不存在，流可能先发送 null
  /// - 任务删除后，流发送 null 或完成
  Stream<UploadTask?> watchTaskById(int id);
  
  /// 监听指定用户的任务变化
  /// 
  /// [userId] 用户 ID
  /// 
  /// Returns: 该用户的任务列表流
  Stream<List<UploadTask>> watchTasksByUserId(String userId);
  
  /// 监听指定状态的任务变化
  /// 
  /// [status] 任务状态
  /// 
  /// Returns: 该状态的任务列表流
  Stream<List<UploadTask>> watchTasksByStatus(UploadTaskStatus status);
  
  /// 监听上传中的任务
  /// 
  /// 等价于 watchTasksByStatus(UploadTaskStatus.uploading)
  Stream<List<UploadTask>> watchUploadingTasks();
  
  /// 监听待上传的任务
  /// 
  /// 等价于 watchTasksByStatus(UploadTaskStatus.pending)
  Stream<List<UploadTask>> watchPendingTasks();
  
  /// 监听所有进度变化
  /// 
  /// Returns: 进度列表流
  Stream<List<UploadProgress>> watchAllProgress();
  
  /// 监听指定任务的进度变化
  /// 
  /// [taskId] 任务 ID
  /// 
  /// Returns: 进度流，高频更新
  Stream<UploadProgress?> watchProgressByTaskId(int taskId);
  
  // ==================== Statistics ====================
  
  /// 获取任务统计信息
  /// 
  /// Returns: Map<状态, 数量>
  /// 
  /// Example:
  /// ```dart
  /// final stats = await repository.getTaskStatistics();
  /// print('Pending: ${stats[UploadTaskStatus.pending]}');
  /// print('Uploading: ${stats[UploadTaskStatus.uploading]}');
  /// print('Completed: ${stats[UploadTaskStatus.completed]}');
  /// ```
  Future<Map<UploadTaskStatus, int>> getTaskStatistics();
  
  /// 获取指定用户的任务数量
  /// 
  /// [userId] 用户 ID
  /// 
  /// Returns: 任务总数
  Future<int> getTaskCountByUserId(String userId);
  
  /// 获取指定组别的任务数量
  /// 
  /// [groupId] 分组 ID
  /// 
  /// Returns: 任务总数
  Future<int> getTaskCountByGroupId(String groupId);
}

// ==================== Exception Classes ====================

/// Repository 操作异常基类
abstract class RepositoryException implements Exception {
  final String message;
  final Object? cause;
  
  const RepositoryException(this.message, [this.cause]);
  
  @override
  String toString() => 'RepositoryException: $message${cause != null ? ' (cause: $cause)' : ''}';
}

/// 数据不存在异常
/// 
/// 用于查询或更新不存在的数据时抛出
class DataNotFoundException extends RepositoryException {
  const DataNotFoundException(String message, [Object? cause]) 
      : super(message, cause);
  
  @override
  String toString() => 'DataNotFoundException: $message';
}

/// 数据冲突异常
/// 
/// 用于 ID 重复、唯一约束冲突等情况
class DataConflictException extends RepositoryException {
  const DataConflictException(String message, [Object? cause])
      : super(message, cause);
  
  @override
  String toString() => 'DataConflictException: $message';
}

/// 数据验证异常
/// 
/// 用于数据不符合验证规则时抛出
class DataValidationException extends RepositoryException {
  final Map<String, String>? fieldErrors;
  
  const DataValidationException(
    String message, [
    Object? cause,
    this.fieldErrors,
  ]) : super(message, cause);
  
  @override
  String toString() {
    final errors = fieldErrors?.entries.map((e) => '${e.key}: ${e.value}').join(', ');
    return 'DataValidationException: $message${errors != null ? ' ($errors)' : ''}';
  }
}

// ==================== Summary ====================

/// 接口契约总结
/// 
/// 方法数量: 39
/// - CRUD: 7 methods
/// - Query: 5 methods
/// - State Management: 5 methods
/// - Progress: 4 methods
/// - Stream: 8 methods
/// - Statistics: 3 methods
/// - Exceptions: 3 classes
/// 
/// 设计原则:
/// - 所有方法异步（Future/Stream）
/// - 使用领域模型对象
/// - 明确的异常处理
/// - 清晰的文档注释
/// - 示例代码辅助理解
/// 
/// 实现要求:
/// - pipeline_repository 必须实现所有方法
/// - 遵循文档中的异常约定
/// - Stream 订阅后立即发送当前数据
/// - 批量操作使用事务
/// - 优化高频操作（updateProgress）
```

